<?php

declare(strict_types=1);

namespace App\Dao;

use App\Constants\ErrorCode;
use App\Exception\BusinessException;
use App\Model\Model;

abstract class AbstractDao
{
    protected $defaultFields = [];

    /**
     * @param array $where
     * @param array $field 获取字段
     * @return \Hyperf\Database\Model\Builder|\Hyperf\Database\Model\Model|object|null
     */
    public function first(array $where, array $field = [])
    {
        $field = $this->setField($field);
        return $this->where($where)->select($field)->first();
    }

    /**
     * @param array $where
     * @param array|string[] $field
     * @return \Hyperf\Database\Model\Collection
     */
    public function select(array $where, array $field = [], array $params = [])
    {
        $field = $this->setField($field);

        $query = $this->where($where);
        $query->select($field);

        $query = $this->setParams($query, $params);

        return $query->get();
    }

    /**
     * @param array $where
     * @param int $perPage
     * @param array $field
     * @param array $params
     * @return \Hyperf\Contract\LengthAwarePaginatorInterface
     */
    public function paginate(
        array $where,
        int $perPage = 20,
        array $field = [],
        array $params = []
    ): \Hyperf\Contract\LengthAwarePaginatorInterface
    {
        $field = $this->setField($field);

        $query = $this->where($where);
        $query->select($field);

        $query = $this->setParams($query, $params);

        return $query->paginate($perPage);
    }

    /**
     * @param array $where
     * @return \Hyperf\Database\Concerns\BuildsQueries|\Hyperf\Database\Model\Builder|mixed
     */
    public function where(array $where): \Hyperf\Database\Model\Builder
    {
        return Model::query();
    }


    private function setField(array $field)
    {
        if (empty($field)) {
            $field = empty($this->defaultFields) ? ['*'] : $this->defaultFields;
        }
        return $field;
    }

    /**
     * @param \Hyperf\Database\Model\Builder $query
     * @param array $params
     * @return \Hyperf\Database\Model\Builder
     */
    private function setParams(\Hyperf\Database\Model\Builder $query, array $params)
    {
        //不常用：orderBy,groupBy,having,whereIn...（可自封装）
        if (isset($params['orderBy'])) {
            $query->orderBy($params['orderBy'][0], $params['orderBy'][1]);
        }

        if (isset($params['groupBy'])) {
            foreach ($params['groupBy'] as $v) {
                $query->groupBy($v);
            }
        }

        if (isset($params['having'])) {
            $query->having($params['having'][0], $params['having'][1], $params['having'][2]);
        }
        return $query;
    }

    public function firstOrThrow(array $where, int $errorCode = 0)
    {
        $model = $this->first($where);

        if (!$model) {
            throw new BusinessException($errorCode ?: ErrorCode::MODEL_NOT_FOUNT);
        }

        return $model;
    }

}